using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;

[DefaultExecutionOrder(-1)]		//load early
public unsafe class SceneLoader : MonoBehaviour
{
	[System.Serializable]
	public struct SceneLoad
	{
		public bool enabled;
		public int buildIndex;		//TODO: make nicer dropdown that reads the build settings
		public sbyte delayNumFrames;
		public bool waitForLastScene;
		public bool async;
	}
	public enum Sequence
	{
		None,
		Cluster,
		Infotainment,
		ADAS
	}
	public Sequence activeSequence = Sequence.Cluster;
	public bool debugLog;
	public SceneLoad[] sequenceCluster;
	public SceneLoad[] sequenceInfotainment;
	public SceneLoad[] sequenceADAS;
	private int numScenesLoading = 1;	//we have to start with 1 because MainScene also calls OnSceneLoaded
	
	private void Awake()	//we have to use Awake, otherwise the initial scene will not be fully loaded for the first frame
	{
		if (debugLog)
			Debug.Log("[TIMING::LOADED] SceneLoader.Awake");
		
		//start loading scenes
		switch (activeSequence)
		{
			case Sequence.Cluster:
				StartCoroutine(LoadScenes(sequenceCluster));
				break;
			case Sequence.Infotainment:
				StartCoroutine(LoadScenes(sequenceInfotainment));
				break;
			case Sequence.ADAS:
				StartCoroutine(LoadScenes(sequenceADAS));
				break;
		}
	}
	
	private IEnumerator LoadScenes(SceneLoad[] seq)
	{
		SceneManager.sceneLoaded += OnSceneLoaded;
		
		int sceneCount = seq.Length;
		for (int i=0; i<sceneCount; i++)
		{
			SceneLoad s = seq[i];
			if (s.enabled)
			{
				sbyte delay = s.delayNumFrames;
				
				//if -1, fir wait for the previous scene has finished loading (otherwise we just wait a certain amount of frames)
				if (s.waitForLastScene)
				{
					while (numScenesLoading != 0)
					{
						//Debug.Log("wait for scene loads to complete");
						yield return null;
					}
				}
				
				//wait as many frames as defined
				while (delay > 0)
				{
					delay--;
					//Debug.Log($"delay scene load: {delay}");
					yield return null;
				}
				
				//load scene
				if (debugLog)
					Debug.Log($"start load scene {s.buildIndex} in frame {Time.frameCount}");
				numScenesLoading++;
				if (s.async)
					SceneManager.LoadSceneAsync(s.buildIndex, LoadSceneMode.Additive);
				else
					SceneManager.LoadScene(s.buildIndex, LoadSceneMode.Additive);
			}
		}
	}
	
	private void OnSceneLoaded(UnityEngine.SceneManagement.Scene scene, LoadSceneMode mode)
	{
		numScenesLoading--;
		if (debugLog)
			Debug.Log($"[TIMING::LOADED] Scene {scene.name} in frame {Time.frameCount}");
	}
	
	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}
}